use lipo_base::ltools::{
    lconvert,
    parser::{ByteParser, ParseError},
};
use num_enum::{IntoPrimitive, TryFromPrimitive};
use tokio::net::windows::named_pipe::PipeMode::Message;

#[derive(Debug, Default, Clone)]
pub struct LMessage {
    id: String,            // message id
    group_type: GroupType, // group type 单聊0，群聊1
    group_id: String,      // 群聊的话，有一个群聊的ID
    send_id: String,       // 发送者的ID
    // type text-0, image-1, audio-2, video-3, file-4,    一个连接， 一个通知  已读  未读
    // 阅后即焚text-10, image-11, audio-12, video-13, file-14，  开始
    // 撤回-81， 加入群聊，创建群聊
    message_type: MessageType, // 上述type
    content: String,           // 发送的内容。
    extram_type: ExtramType,   // 扩展类型 // 没有的话为 0
    extram: String,            // 扩展字段
}

impl LMessage {
    pub fn new(
        id: String,
        send_id: String,
        group_type: GroupType,
        group_id: String,
        message_type: MessageType,
        content: String,
        extram_type: ExtramType,
        extram: String,
    ) -> Self {
        LMessage {
            id,
            group_type,
            group_id,
            send_id,
            message_type,
            content,
            extram_type,
            extram,
        }
    }
    pub fn new_l(
        id: String,
        send_id: String,
        group_type: GroupType,
        group_id: String,
        message_type: MessageType,
        content: String,
    ) -> Self {
        LMessage {
            id,
            group_type,
            group_id,
            send_id,
            message_type,
            content,
            extram_type: ExtramType::None,
            extram: "".to_string(),
        }
    }


    pub fn new_s(
        id: String,
        send_id: String,
        message_type: MessageType,
        content: String,
    ) -> Self {
        LMessage {
            id,
            group_type:GroupType::Single,
            group_id:"".to_string(),
            send_id,
            message_type,
            content,
            extram_type: ExtramType::None,
            extram: "".to_string(),
        }
    }

    pub fn to_vec(&self) -> Vec<u8> {
        let mut total_len: usize = 3; //1+1+1;
        let id_v = self.id.as_bytes();
        let id_len = id_v.len();
        total_len += 2 + id_len;

        let send_id_v = self.send_id.as_bytes();
        let send_id_len = send_id_v.len();
        total_len += 2 + send_id_len;

        let mut group_id_len = 0;
        let group_id_v = if self.group_type == GroupType::Group {
            let group_id_v = self.group_id.as_bytes();
            group_id_len = group_id_v.len();
            total_len += 2 + group_id_len;
            Some(group_id_v)
        } else {
            None
        };

        let content_v = self.content.as_bytes();
        let content_len = content_v.len();
        total_len += 4 + content_len;

        let mut extram_len = 0;
        let extram_v = if self.extram_type != ExtramType::None {
            let extram_v = self.extram.as_bytes();
            extram_len = extram_v.len();
            total_len += 4 + extram_len;
            Some(extram_v)
        } else {
            None
        };

        let mut m_vec: Vec<u8> = Vec::with_capacity(total_len);
        // 1. group_type
        m_vec.push(self.group_type.clone().into());
        // 2. message_type
        m_vec.push(self.message_type.clone().into());
        // 3. extram_type
        m_vec.push(self.extram_type.clone().into());
        
        // 5. message id
        lconvert::vec_in_u16(&mut m_vec, id_len as u16);
        println!("id: m_vec: {:?}", m_vec);
        m_vec.extend_from_slice(id_v);
        // 6. send id
        lconvert::vec_in_u16(&mut m_vec, send_id_len as u16);
        m_vec.extend_from_slice(send_id_v);
        // 7. group_id 如果有的话
        if let Some(g) = group_id_v {
            lconvert::vec_in_u16(&mut m_vec, group_id_len as u16);
            m_vec.extend_from_slice(g);
        }
        // 8. content
        lconvert::vec_in_u32(&mut m_vec, content_len as u32);
        m_vec.extend_from_slice(content_v);
        // 9 extram 扩展字段
        if let Some(ev) = extram_v {
            lconvert::vec_in_u32(&mut m_vec, extram_len as u32);
            m_vec.extend_from_slice(ev);
        }
        m_vec
    }

    pub fn from_vec(&mut self, m_vec: &[u8]) -> Result<(), ParseError> {
        let mut parser = ByteParser::new(m_vec);
        // 1. group_type
        self.group_type = GroupType::try_from(parser.parse_u8()?).unwrap_or_default();
        // 2. message_type
        self.message_type = MessageType::try_from(parser.parse_u8()?).unwrap_or_default();
        // 3. extram_type
        self.extram_type = ExtramType::try_from(parser.parse_u8()?).unwrap_or_default();
        // 5. message id
        self.id = parser.parse_str_u16()?;
        // 6. send id
        self.send_id = parser.parse_str_u16()?;
        // 7.  group_id 如果有的话
        if self.group_type == GroupType::Group {
            self.group_id = parser.parse_str_u16()?;
        }
        // 8. content
        self.content = parser.parse_str_u32()?;
        // 9 extram 扩展字段
        if self.extram_type != ExtramType::None {
            self.extram = parser.parse_str_u32()?;
        }
        Ok(())
    }
}

#[derive(Debug, Eq, PartialEq, Clone, IntoPrimitive, TryFromPrimitive, Default)]
#[repr(u8)]
pub enum GroupType {
    #[default]
    Single,
    Group,
}

#[derive(Debug, Eq, PartialEq, Clone, IntoPrimitive, TryFromPrimitive, Default)]
#[repr(u8)]
pub enum ExtramType {
    #[default]
    None,
}

#[derive(Debug, Eq, PartialEq, Clone, IntoPrimitive, TryFromPrimitive, Default)]
#[repr(u8)]
pub enum MessageType {
    #[default]
    Text,
    Image,
    Audio,
    Video,
}
